package org.lsj.kit.config.SpringSecurityImpl;

import org.lsj.kit.config.ConfigAttributeCache;
import org.springframework.security.access.*;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * Created by 豆腐干Sama on 2019/3/4.
 *查询当前访问的资源需要什么权限(角色)才能访问
 */
@Service
public class KitSecurityMetadataSource implements FilterInvocationSecurityMetadataSource{
    @Override
    public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException {
        String url = ((FilterInvocation) object).getRequestUrl();
        String contextPath = ((FilterInvocation) object).getRequest().getContextPath();
        int paramsIndexOf = url.indexOf("?");
        if (paramsIndexOf != -1) {
            url = url.substring(0,paramsIndexOf);
        }
        List<ConfigAttribute> result = ConfigAttributeCache.get(contextPath + url);

        /**
         *
         * 以下注掉的代码：
         * 针对于我们自定义的拦截器和自定义的FilterInvocationSecurityMetadataSource
         * 当一个资源关联的ConfigAttribute为空的时候，是不会对该资源进行认证的参见AbstractSecurityInterceptor.beforeInvocation()方法中判断attributes的代码
         *
         * 例如自定义登陆页面 /login 如果给/login关联一个默认的权限（ROLE_ANONYMOUS：因为spring会给未登录用户添加一个ROLE_ANONYMOUS权限）会先执行自定义的代码，
         * 然后在执行FilterSecurityInterceptor 这时如果不在配置类中给login加上permitAll()就验证不通过，因为我的配置类有.anyRequest().authenticated();这一行
         * 这两个过滤器都认证通过才能通过,结论就是当我的url没有配置到数据库中就不走自定义的验证流程，会走FilterSecurityInterceptor拦截器的验证流程
         * */

        /**
         可以把这个resource当成是刚刚初始化的对象，还没有关联角色,这种情况则只有超级管理员能访问
        if (CollectionUtils.isEmpty(result)) {
            result = new ArrayList<>();
            result.add(new org.springframework.security.access.SecurityConfig("ROLE_BASE"));
        }*/
        return result;
    }

    @Override
    public Collection<ConfigAttribute> getAllConfigAttributes() {
        return null;
    }

    @Override
    public boolean supports(Class<?> clazz) {
        return true;
    }
}
